import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.*;
import java.util.regex.Pattern;


import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.parser.Tag;
import org.jsoup.select.Elements;


public class WebPage {


    //members
    private String url; //page address
    private Set<String> links; //adjacency list
    private String urlContent;
    private Elements paragraphs;


    //constructor
    public WebPage(String url) {
        this.url = url;
        links = new HashSet<String>();
        paragraphs = new Elements();
        urlContent = getURLContent(url);
        extractLinksFromParagraph(urlContent);
    }

    private void extractLinksFromParagraph(String html) {

        final String prefix = "http://simple.wikipedia.org";
        Document document = Jsoup.parse(html);
        Element pageContent = document.select("div#mw-content-text").get(0);

        if (pageContent == null) {
            return;
        }
        Tag pTag = Tag.valueOf("p");

        int i = 0;
        //find the first p tag
        while (i <= pageContent.children().size() && !pageContent.child(i).tag().equals(pTag) ){
            i++;
        }
        while (i <= pageContent.children().size() && pageContent.child(i).tag().equals(pTag) ) {
            paragraphs.add(pageContent.child(i));
            i++;
        }

        if (paragraphs.isEmpty()) {
            return;
        }

        for (Element p: paragraphs){
        Elements linkElements = p.getElementsByTag("a");

            String temp;
            for (Element e : linkElements) {
                temp = e.attr("href");
                if (temp.startsWith("/wiki/")) {
                    links.add(prefix + temp);
                }
            }
        }
    }

    //public methods

    public String getUrl() {
        return url;
    }

    public Set<String> getLinks() {
        return links;
    }



    @Override
    public String toString() {
        return "url = " + url;
    }

    /**
     * Receives a url of a page and returns the page content as a string
     */
    private String getURLContent(String url) {

        String text;
        StringBuilder stringbuilder = new StringBuilder();

        try {
            URL my_url = new URL(url);
            BufferedReader br = new BufferedReader(new InputStreamReader(my_url.openStream()));

            while ((text = br.readLine()) != null) {
                stringbuilder.append(text);
                stringbuilder.append(System.getProperty("line.separator"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return stringbuilder.toString();
    }



    public boolean isRoyal() {

        Document document = Jsoup.parse(urlContent);
        Elements infoBox = document.select("table.infobox");

        if (!infoBox.isEmpty()) { //info-box found
            //if has infobox but not human
            if (!hasProperty(infoBox.get(0), "Born")) {
                return false;
            }
            if (hasProperty(infoBox.get(0), "House", "House of Windsor")) {
                return true;
            }
            if (isElementContainsWords(infoBox.get(0), Royal.royalWords)) {
                return true;
            }
        }
          //no infobox
        else {
            if (!isHuman()) {
                return false;
            }
        }

        //we found a person, now check if royal
        Element categoryLinks = document.getElementById("mw-normal-catlinks");
        if (categoryLinks != null) {
            Elements linkList = categoryLinks.getElementsByTag("ul");
            if (isElementContainsWords(linkList.get(0), Royal.royalWords))
                return true;
        }

        return false;
    }


    private boolean hasProperty(Element element, String th) {
        Elements headers = element.getElementsByTag("th");
        for (Element h : headers) {
            if (h.text().equals(th))
                return true;
        }
        return false;
    }

    private boolean hasProperty(Element element, String th, String td) {
        Elements headers = element.getElementsByTag("tr");
        for (Element h : headers) {
            if (h.getElementsByTag("th").text().equals(th) && h.getElementsByTag("td").text().contains(td))
                return true;
        }
        return false;
    }

    /*
    return true if finds at least one word from our "buzz words" array
     */
    private boolean isElementContainsWords(Element element, String[] wordsArray) {
        String elementContent = element.text().toLowerCase();
        for (int i = 0; i < wordsArray.length; i++) {
            if (elementContent.contains(wordsArray[i])) {
                return true;
            }
        }
        return false;
    }

    private boolean isHuman() {
        String text = paragraphs.text();
        if (text.contains(" born "))
            return true;
        return false;
    }
}
